<?php

namespace App\Http\Middleware;

use App\Exceptions\MemberException;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;

class server_authrization
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle( Request $request, Closure $next )
    {
        // 服务系统
        $system = $request->route()->uri;

        // 服务密钥
        $key = Config::get( 'user.' . $system . '_key' );

        // 服务名称
        $service = $request->post( 'service' );

        // 服务参数
        $content = $request->post( 'content' );
        
        // 服务时间
        $timestamp = $request->post( 'timestamp' );

        // 服务签名
        $signature = $request->post( 'signature' );

        if( $service && $content && $timestamp && $signature )
        {
            // 服务参数解码
            $data = json_decode( base64_decode( $content, true ), true );
            
            // 验证签名
            if( ! $this->verify_signature( $service, $key, $data, $timestamp, $signature ) )
            {
                return response()->json( [ 'code' => 10004, 'message' => 'error signature' ] );
            }

            // request post数据重载
            $request->_post = $request->post();
            $request->replace( $data );
        }
        
        else
        {
            return response()->json( [ 'code' => 10003, 'message' => 'error service' ] );
        }

        return $next( $request );
    }

    /**
     * 验证签名
     * 
     * @param string $service 服务名称
     * @param string $key 加密密钥
     * @param array $data 参数
     * @param int $timestamp 时间戳
     * @param string $signature 签名
     */
    protected function verify_signature( $service, $key, $data, $timestamp, $signature )
    {
        ksort( $data ); // 数据进行ascii码排序
        
        $data = http_build_query( $data ); // 数据转url
        
        $encrypt = strtolower( md5( $service . $key . $data . $timestamp ) ); // 加密数据
        
        return $encrypt === $signature; // 判断加密是否正确
    }
}
